/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package taskmanager2ndedition.server;

import java.io.IOException;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import taskmanager2ndedition.*;
import taskmanager2ndedition.exceptions.*;
import taskmanager2ndedition.server.Server;

/**
 *
 * @author denaas
 */
public class ServerController {
    private SecurityManager securityManager;
    private UserManager userManager;
    private SessionManager sessionManager;
    private int timeout = 15000;
    
    public static void main(String[] args){
        new ServerController();
    }
    
    public ServerController(){
        StorageFactory userFactory = new MySQLUserStorageFactory();
        StorageFactory taskFactory = new MySQLTaskStorageFactory();
        
        userManager = new UserManager(userFactory.createInstance());
        TaskManager.Init(taskFactory.createInstance());
        sessionManager = new SessionManager();
        securityManager = new SecurityManager(sessionManager, userManager);
        CmdInterpretator.setController(this);
        
        ServerConnection.Init(timeout);
        Thread server;
        try {
            server = new Thread(new Server(5555));
            server.start();
        } catch (IOException ex) {
            Logger.getLogger(ServerController.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }
    
    public void sendErrorMessage(Exception ex, CmdInterpretator cmdInterpretator){
        List params = new LinkedList();
        params.add(ex);
        cmdInterpretator.generateResponce(new Cmd(ex.toString(), params));
    }
    
    private void sendSuccessful(String method, CmdInterpretator cmdInterpretator){
        List params = new LinkedList();
        params.add("successful");
        cmdInterpretator.generateResponce(new Cmd(method, params));
    }

    public void changePassword(String oldPassword, String newPassword, CmdInterpretator cmdInterpretator){
        try {
            int sessionId = cmdInterpretator.getConnection().getSessionId();
            User user = securityManager.getSelf(sessionId);
            if (!securityManager.checkPassword(oldPassword, user.getPassword()))
                throw new WrongPasswordException();            
            userManager.editUser(user.getId(), newPassword);      
          
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        }
        
        sendSuccessful("changePassword", cmdInterpretator);
    }    
    
    public void addTask(Task task, CmdInterpretator cmdInterpretator){
        try {
            int sessionId = cmdInterpretator.getConnection().getSessionId();
            User user = securityManager.impersonate(sessionId, task.getUserId());
            user.getTaskManager().addTask(task);
            
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        }
        
        sendSuccessful("addTask", cmdInterpretator);
    }
    
    public void deleteUser(Integer userId, CmdInterpretator cmdInterpretator){
        try {
            int sessionId = cmdInterpretator.getConnection().getSessionId();
            User self = securityManager.getSelf(sessionId);
            if (!securityManager.checkPrivileges(self))
                throw new LowPrivilegesException();
            User user = userManager.findById(userId);
            userManager.deleteUser(user.getId());
            
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        }
        
        sendSuccessful("deleteUser", cmdInterpretator);
    }
    
    public void editTask(Task task, CmdInterpretator cmdInterpretator){
        try {
            int sessionId = cmdInterpretator.getConnection().getSessionId();
            User user = securityManager.impersonate(sessionId, task.getUserId());
            user.getTaskManager().editTask(task);
            
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        }
        
        sendSuccessful("editTask", cmdInterpretator);
    }
    
    public void getUserLogin(CmdInterpretator cmdInterpretator){
        try {
            int sessionId = cmdInterpretator.getConnection().getSessionId();
            User user = securityManager.getSelf(sessionId);
            
            List params = new LinkedList();
            params.add(user.getLogin());
            cmdInterpretator.generateResponce(new Cmd("getUserLogin", params));
            
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        }
    }

    public void isAdmin(CmdInterpretator cmdInterpretator){
        try {
            int sessionId = cmdInterpretator.getConnection().getSessionId();
            User user = securityManager.getSelf(sessionId);

            List params = new LinkedList();
            params.add(securityManager.checkPrivileges(user));
            cmdInterpretator.generateResponce(new Cmd("isAdmin", params));
            
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        }
    }
    
    public void login(String login, String password, CmdInterpretator cmdInterpretator){
        try {
            Session session = securityManager.authorize(login, password); 
            cmdInterpretator.getConnection().setLoggedIn(true);
            cmdInterpretator.getConnection().setSessionId(session.getId());

            List params = new LinkedList();
            params.add(session.getUser().getId());
            cmdInterpretator.generateResponce(new Cmd("login", params));
            
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        }
    }
    
    public void logout(CmdInterpretator cmdInterpretator){
        try {
            int sessionId = cmdInterpretator.getConnection().getSessionId();          
            sessionManager.closeSession(sessionId);
            cmdInterpretator.getConnection().close();
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        }
        
        sendSuccessful("logout", cmdInterpretator);
    }
    
    public void register(String login, String password, CmdInterpretator cmdInterpretator){
        try {
            userManager.findByLogin(login);
            throw new UserAlreadyExistsException();
        } catch (UserNotFoundException ex) {
            userManager.addUser(login, password);
            sendSuccessful("register", cmdInterpretator);
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        }
    }
    
    public void addUser(String login, String password, CmdInterpretator cmdInterpretator){
        try {
            int sessionId = cmdInterpretator.getConnection().getSessionId();
            User user = securityManager.getSelf(sessionId);
            if (!securityManager.checkPrivileges(user))
                throw new LowPrivilegesException();
            userManager.findByLogin(login);
            throw new UserAlreadyExistsException();  
            
        } catch (UserNotFoundException ex) {
            userManager.addUser(login, password);
            sendSuccessful("addUser", cmdInterpretator);
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        }             
    }
    
    public void removeTask(Task task, CmdInterpretator cmdInterpretator){
        try {
            int sessionId = cmdInterpretator.getConnection().getSessionId();
            User user = securityManager.impersonate(sessionId, task.getUserId());
            user.getTaskManager().removeTask(task.getId());
            sendSuccessful("removeTask", cmdInterpretator);
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        } 
    }
    
    public void updateTasks(Integer userId, CmdInterpretator cmdInterpretator){
        try {
            int sessionId = cmdInterpretator.getConnection().getSessionId();
            User user = securityManager.impersonate(sessionId, userId);

            List params = new LinkedList();
            if (securityManager.checkPrivileges(user)){
                params.add(TaskManager.getAllModified());           
            }
            else{
                params.add(user.getTaskManager().getGroupModified());
            }
            cmdInterpretator.generateResponce(new Cmd("updateTasks", params));
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        } 
        
    }
    
    public void updateUsers(CmdInterpretator cmdInterpretator){
        try {
            int sessionId = cmdInterpretator.getConnection().getSessionId();
            User user = securityManager.getSelf(sessionId);

            List params = new LinkedList();
            if (securityManager.checkPrivileges(user)){
                params.add(userManager.getModified());           
            }
            cmdInterpretator.generateResponce(new Cmd("updateUsers", params));
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        }
    }
    
    public void updateStatistics(Integer userId, CmdInterpretator cmdInterpretator){
        try {
            int sessionId = cmdInterpretator.getConnection().getSessionId();
            User user = securityManager.impersonate(sessionId, userId);

            List params = new LinkedList();
            if (securityManager.checkPrivileges(user)){
                params.add(user.getTaskManager().calculateAllStatistics());
            } else {
                params.add(user.getTaskManager().calculateGroupStatistics());
            }
            cmdInterpretator.generateResponce(new Cmd("updateStatistics", params));
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        }
    }
    
    public void validateDate(Integer userId, Date date, CmdInterpretator cmdInterpretator){
        try {
            int sessionId = cmdInterpretator.getConnection().getSessionId();
            User user = securityManager.impersonate(sessionId, userId);
            List params = new LinkedList();
            params.add((Boolean)user.getTaskManager().validateDate(date));
            cmdInterpretator.generateResponce(new Cmd("validateDate", params));
            
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        } 
    }
    
    public void getAllTasks(Integer userId, CmdInterpretator cmdInterpretator){
        try {
            int sessionId = cmdInterpretator.getConnection().getSessionId();
            User user = securityManager.impersonate(sessionId, userId);

            List params = new LinkedList();
            if (securityManager.checkPrivileges(user)){
                params.add(TaskManager.getAll());           
            }
            else{
                params.add(user.getTaskManager().getGroup());
            }
            cmdInterpretator.generateResponce(new Cmd("getAllTasks", params));
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        }        
    }
    
    public void getAllUsers(CmdInterpretator cmdInterpretator){
        try {
            int sessionId = cmdInterpretator.getConnection().getSessionId();
            User user = securityManager.getSelf(sessionId);

            List params = new LinkedList();
            if (securityManager.checkPrivileges(user)){
               params.add(userManager.getAll());
            }
            cmdInterpretator.generateResponce(new Cmd("getAllUsers", params));
        } catch (Exception ex) {
            sendErrorMessage(ex, cmdInterpretator);
        }        
    }
}
